<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>07_Promise的API</title>
</head>

<body>
  <!-- 
    1. Promise构造函数: new Promise (executor){}
      executor函数: 是同步执行的, (resolve, reject) => {}
      resolve函数: 调用 resolve将 Promise实例内部状态改为成功(fulfilled)
      reject函数: 调用 reject将 Promise实例内部状态改为失败(rejected)
      说明: executor函数会在 Promise内部立即同步调用, 异步代码放在 executor函数中

    2. Promise.prototype.then方法: Promise实例.then(onFulfilled, onRejected)
      onFulfilled: 成功的回调函数 (value) => {}
      onRejected: 失败的回调函数 (reason) => {}
      特别注意(难点): then方法会返回一个新的 Promise 实例对象

    3. Promise.prototype.catch方法: Promise实例.catch(onRejected)
      onRejected: 失败的回调函数 (reason) => {}
      说明: catch方法是 then方法的语法糖, 相当于: then(undefined, onRejected)

    4. Promise.resolve方法: Promise.resolve(value)
      说明: 用于快速返回一个状态为 fulfilled或rejected 的Promise实例对象
      备注: value的值可能是: (1)非 Promise值  (2)Promise值

    5. Promise.rejected方法: Promise.reject(reason)
      说明: 用于快速返回一个状态为 rejected的 Promise实例对象

    6. Promise.all方法: Promise.all(promiseArr)
      promiseAll: 包含n个 Promise实例的数组
      说明: 返回一个新的 Promise实例, 只有所有的 Promise都成功才成功, 只要有一个失败了就直接失败.

    7. Promise.race方法: Promise.race(promiseArr)
      promiseAll: 包含n个 Promise实例的数组
      说明: 返回一个新的 Promise实例, 成功还是失败? 以最先出结果的 Promise为准
  -->

  <script>
    // #region 验证: then 方法会返回一个新的 Promise实例对象, (暂且不研究返回的这个新的Promise实例状态怎么变化)
    // const p = new Promise((resolve,reject) => {
    //   setTimeout(() => {
    //     resolve(100);
    //   }, 1000)
    // });

    // const x = p.then(
    //   (value) => { console.log('成功了:', value) },
    //   (reason) => { console.log('失败了:', reason) }
    // )
    // console.log(x);
    // #endregion


    // #region 验证: Promise.prototype.catch方法 是 then方法的语法糖
    // const p = new Promise((resolve,reject) => {
    //   setTimeout(() => {
    //     reject(-100);
    //   }, 1000)
    // });

    // p.then(
    //   undefined,
    //   (reason) => { console.log('失败了1:', reason) }
    // );

    // p.catch (
    //   (reason) => { console.log('失败了2:', reason) }
    // );
    // #endregion


    // #region 演示: Promise.prototype.then方法的注意点
    // const p = new Promise((resolve,reject) => {
    //   setTimeout(() => {
    //     reject(-100);
    //   },1000);
    // });

    // p.then((value) => { console.log(value)}),
    // p.catch((reason) => { console.log(reason)})

    // 注意: 此时控制台输出什么?
    // 一般都会想到 输出了 .catch的回调 输出了 -100
    // 但是: 不然
    // 首先分析:
    // .then  这一组回调都经历了什么
    // .catch 这一组回调都经历了什么

    // p.then(
    //   (value) => {console.log(value)},
    //   // 指定了成功的回调
    //   // undefined
    //   // 失败的回调没有指定 用undefined占位
    //   // 问题就出现在这里, 失败的回调没有被指定, 没有捕获到错误.
    //   // 控制台就将 没有被捕获的错误 已报错的形式显示出来.
    //   // 接下来可以 试着指定一个失败的回调, 来捕获这个错误.
    //   // 将上面的 undefined注释掉
    //   (reason) => {console.log(reason)},
    //   // 可以看到 报错没有了 这个错误被捕捉到了,并且console.log打印出来了
    // )
    // p.catch(
    //   (reason) => {console.log(reason)},
    //   // 指定了失败的回调
    // )
    // #endregion


    // #region 演示: Promise.resolve方法 的使用
    // const p = new Promise((resolve,reject) => {
    //   resolve(100);
    // });
    // p.then(
    //   (value) => { console.log(value)},
    // );

    // // 等价于

    // const p1 = Promise.resolve(100);
    // p1.then((value) => { console.log(value) });
    // #endregion


    // #region 演示: Promise.reject方法 的使用
    // const p = new Promise((resolve,reject) => {
    //   reject(-100);
    // });
    // p.then(
    //   (value) => { console.log(value) },
    //   (reason) => { console.log(reason) }
    // );
    // p.catch((reason) => { console.log(reason) });

    // // 等价于

    // const p1 = Promise.reject(-100);
    // p1.then(
    //   (value) => { console.log(value) },
    //   (reason) => { console.log(reason) }
    // );
    // p1.catch((reason) => { console.log(reason) });
    // #endregion


    // #region 演示: Promise.resolve方法 的返回状态
    // const p = Promise.resolve(false);
    // p.then((value) => { console.log('成功了:', value) });
    // const p1 = Promise.resolve('false');
    // p1.then((value) => { console.log('成功了:', value) });
    // const p2 = Promise.resolve(123);
    // p2.then((value) => { console.log('成功了:', value) });
    // const p3 = Promise.resolve(undefined);
    // p3.then((value) => { console.log('成功了:', value) });

    // const p4 = Promise.resolve(100);
    // const p5 = Promise.resolve(p4);
    // p5.then((value) => { console.log('成功了:', value) });

    // const p6 = Promise.reject(-100);
    // const p7 = Promise.resolve(p6);
    // p7.then(
    //   (value) => { console.log('成功了:', value) },
    //   (reason) => { console.log('失败了:', reason) },
    // );

    // 结论: 
    //      1. 传入一个 非Promise的值, resolve方法 返回的都是一个成功的 Promise实例对象
    //      2. 传入一个 Promise实例对象(成功),  resolve方法 返回的是一个成功的 Promise实例对象
    //      3. 传入一个 Promise实例对象(失败),  resolve方法 返回的是一个失败的 Promise实例对象
    // #endregion


    // #region 演示: Promise.reject方法 的返回状态
    // const p = Promise.reject(false);
    // p.catch((reason) => { console.log('失败了:', reason) });
    // const p1 = Promise.reject('false');
    // p1.catch((reason) => { console.log('失败了:', reason) });
    // const p2 = Promise.reject(123);
    // p2.catch((reason) => { console.log('失败了:', reason) });
    // const p3 = Promise.reject(undefined);
    // p3.catch((reason) => { console.log('失败了:', reason) });

    // const p4 = Promise.reject(100);
    // const p5 = Promise.reject(p4);
    // p5.catch((reason) => { console.log('失败了:', reason) });

    // const p6 = Promise.resolve(-100);
    // const p7 = Promise.reject(p6);
    // p7.catch((reason) => { console.log('失败了:', reason) });

    // 结论: 
    //     无论传入的是 非Promise、还是 成功/失败的Promise, 返回的都是一个 失败的 Promise实例对象
    // #endregion


    // #region 演示: Promise.all方法 的使用
    // const p1 = Promise.resolve('a');
    // const p2 = new Promise((resolve,reject) => {
    //   setTimeout(() => {
    //     resolve('b');
    //   }, 500);
    // });
    // const p3 = new Promise((resolve,reject) => {
    //   setTimeout(() => {
    //     resolve('c');
    //   }, 2000);
    // });

    // const p = Promise.all([p1,p2,p3]);
    // p.then(
    //   (value) => { console.log(value) },
    //   (reason) => { console.log(reason) }
    // );
    // 都成功 以数组的形式 按照顺序依次返回结果
    // 有一个失败 就终止运行, 返回失败的结果
    // #endregion


    // #region 演示: Promise.race方法 的使用
    // const p1 = Promise.resolve('a');
    // const p2 = new Promise((resolve,reject) => {
    //   setTimeout(() => {
    //     reject('b');
    //   }, 500);
    // });
    // const p3 = new Promise((resolve,reject) => {
    //   setTimeout(() => {
    //     resolve('c');
    //   }, 2000);
    // });

    // const p = Promise.race([p1,p2,p3]);
    // p.then(
    //   (value) => { console.log(value) },
    //   (reason) => { console.log(reason) }
    // );
    // 不管 成功/失败 只返回 第一个改变状态的Promise
    // #endregion
  </script>
</body>

</html>
